package main

import "fmt"

func main() {
	//fmt.Println(
	//	lengthOfNonRepeatingSubStr("abcabc"))
	//fmt.Println(
	//	lengthOfNonRepeatingSubStr("bbb"))
	//fmt.Println(
	//	lengthOfNonRepeatingSubStr("pwwadb"))
	//fmt.Println(
	//	lengthOfNonRepeatingSubStr(""))
	//fmt.Println(
	//	lengthOfNonRepeatingSubStr2("一二三二一"))
	fmt.Println(
		lengthOfLongestSubstring("bbb"))
}

func lengthOfNonRepeatingSubStr(s string) int {
	lastOccurred := make(map[byte]int) // 使用map记录某个字符上一次出现的位置，这里的key使用的byte类型，其实使用rune类型更好
	start := 0                         // 记录没有出现重复字符的字符串的最开始的位置
	maxLength := 0                     // 没有出现重复字符的字符串的最长长度
	for i, ch := range []byte(s) {     // 循环读取byte类型的数据，使用rune更好
		// 如果之前已经读取过相同字符的位置，并且该字符上一次出现的位置在start后边，则需要更新start保证字符串没有重复字符
		if lastI, ok := lastOccurred[ch]; ok && lastI >= start {
			start = lastI + 1
		}
		// 对比当前没有重复字符的字符串的长度是否超过当前的最长长度，超过则更新
		if i-start+1 > maxLength {
			maxLength = i - start + 1
		}
		// 将当前字符ch的位置i更新到lastOccurred这个map中
		lastOccurred[ch] = i
	}

	return maxLength
}

// 支持中文字符串
func lengthOfNonRepeatingSubStr2(s string) int {
	lastOccurred := make(map[rune]int) // 使用map记录某个字符上一次出现的位置，这里的key使用的byte类型，其实使用rune类型更好
	start := 0                         // 记录没有出现重复字符的字符串的最开始的位置
	maxLength := 0                     // 没有出现重复字符的字符串的最长长度
	for i, ch := range []rune(s) {     // 循环读取byte类型的数据，使用rune更好
		// 如果之前已经读取过相同字符的位置，并且该字符上一次出现的位置在start后边，则需要更新start保证字符串没有重复字符
		if lastI, ok := lastOccurred[ch]; ok && lastI >= start {
			start = lastI + 1
		}
		// 对比当前没有重复字符的字符串的长度是否超过当前的最长长度，超过则更新
		if i-start+1 > maxLength {
			maxLength = i - start + 1
		}
		// 将当前字符ch的位置i更新到lastOccurred这个map中
		lastOccurred[ch] = i
	}

	return maxLength
}

func lengthOfLongestSubstring(s string) int {
	m := make(map[rune]int)
	max := 0
	start := 0
	for i, letter := range s {
		if old, ok := m[letter]; ok && old >= start {
			start = old + 1
		}
		if i-start+1 > max {
			max = i - start + 1
		}
		m[letter] = i
	}
	return max
}
